import * as THREE from 'three';
import {
  TextureLoader,
  Color,
  Path,
  AmbientLight,
  DirectionalLight,
  PointLight,
  Group,
  RepeatWrapping,
  Vector3,
  PerspectiveCamera,
  OrthographicCamera,
  Box3,
  MeshStandardMaterial,
  MeshMatcapMaterial,
  MeshLambertMaterial,
  MeshBasicMaterial,
  MeshToonMaterial,
  MeshPhongMaterial,
  MeshPhysicalMaterial,
  Mesh,
  PCFSoftShadowMap,
  WebGLRenderer,
  Cache,
  PlaneGeometry,
  Fog,
  Scene
} from 'three';

import MaterialSystem from './material-system.js';
import msfor from './msfor.js';

import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'






function autoClip(camera, object) {
  const box = new Box3().expandByObject(object);

  const size = box.getSize(new Vector3());
  const center = box.getCenter(new Vector3());

  // 方法1：调整相机位置
  const maxDim = Math.max(size.x, size.y, size.z);
  camera.position.copy(center).add(new Vector3(0, 0, maxDim * 2));
  // 方法2：调整相机裁截面
  camera.near = maxDim * 0.1;
  camera.far = maxDim * 10;
  camera.updateProjectionMatrix();
}


class Render3DText extends MaterialSystem {
  #targetRotation = 0;
  #container;
  #controls;
  #camera;

  #group;
  #textGeo;
  #options = {};
  #font;
  constructor(options = {}, container = document.body) {
    super(options);
    this.#container = container;
    const self = this;
    this.size = {
      width: window.innerWidth,
      height: window.innerHeight
    };
    // this.size = { width: window.innerWidth, height: 300 }
    options = this.#setConfig(options);
    this.open(options);
  }

  setOptions(options = {}, callback = () => {}) {
    const self = this;

    options = this.#setConfig(options);
    self.loadTTF(options, (font) => {
      self.#font = font;
      self.refreshText(options)
      callback();
    });
  }

  #setConfig(options = {}) {
    options = Object.assign({
  "materials": [
      /*所以材质可以定制
              说了呀 所以材质可以定制 参数也是 THREE参数位置配置的
              MeshPhysicalMaterial
              MeshToonMaterial
              MeshPhongMaterial
              MeshLambertMaterial
              MeshStandardMaterial
              MeshBasicMaterial
              */
    {
      "type": "MeshPhongMaterial",
      "color": 0xffb6c1,
      "specular": 0xffffff,
      "shininess": 30,
      "transparent": false,
      "opacity": 1.0
    },
    {
      "type": "MeshBasicMaterial",
      "color": 0x000000,
      "transparent": true,
      "opacity": 0.4,
      "depthWrite": false
    }
  ],
  "lights": [
      /*所有灯光可以定制 参数也是 THREE参数位置配置的
           ambientLight
           pointLight
           directionalLight
           
           */
    {
      "type": "DirectionalLight",
      "color": 0xffffff,
      "intensity": 1.5,
      "position": { "x": -0.8, "y": 1.2, "z": 1.5 },
      "castShadow": true,
      "shadow": {
        "mapSize": { "width": 2048, "height": 2048 },
        "bias": -0.001
      }
    },
    {
      "type": "AmbientLight",
      "color": 0x404040,
      "intensity": 0.3
    }
  ],
  "geometry": {
    "type": "TextGeometry",
    "parameters": {
      "bevel": {
        "enabled": true,
        "size": 12,
        "thickness": 16,
        "segments": 32,
        "angle": 0.5,
        "curveSegments": 2
      },
      "depth": 8,
      "steps": 2
    }
  },
  "text": {
    "fontName": "Rounded",
    "fontSize": 140,
    "content": "ABC",
    "charSpacing": 5,
    "lineSpacing": 0,
    "pathOffset": -10
  },
  "camera": {
    /*['Orthographic','Perspective']*/
    "type": "Perspective",
    "perspective": {
      "fov": 45,
      "near": 0.1,
      "far": 3000,
      "position": { "x": 0, "y": 0, "z": 1200 }
    },
    "orthographic": {
      "viewSize": 1000,
      "near": 0.1,
      "far": 3000,
      "position": { "x": 0, "y": 0, "z": 1500 }
    }
  },
  "render": {
    "autoClip": true,
    "background": 0x000000,
    "antialias": true
  }
}, options)



    options.scene = Object.assign({
        background: { color: 0x123abc },
        fog: { color: 0xfffabc },
         
         
      },
      options.scene
    )


    Cache.enabled = true;
    let state = {
      backgroundColor: '#164CCA',
      renderGlithPass: !(window.navigator.userAgent.toLowerCase().indexOf('mobile') > 0)
    }


    this.#options = options;


    return options;

  }
  open(options = {}) {
    this.createThree(options);
    this.initControls();
    const self = this;
    const animate = () => {
      window.requestAnimationFrame(animate);

      self.render();

    }
    animate();
  }


  createThree(options = {}) {
    const self = this;
    const size = this.size;


    this.cameraTarget = new Vector3(
      0, 150, 0);

    this.#group = this.getGrouo();
    this.scene = this.getScene(options.scene);
    this.setupLights(options)
    this.scene.add(this.#group);
    this.#camera = this.createCamera(options);


    // RENDERER

    const renderer = new WebGLRenderer({
      preserveDrawingBuffer: true,
      antialias: true,
      alpha: true
    });
    renderer.shadowMap.enabled = true; // 总开关
    renderer.shadowMap.type = PCFSoftShadowMap; // 阴影类型（平滑阴影）

    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(size.width, size.height);
    this.#container.appendChild(renderer.domElement);
    renderer.setClearAlpha(0);
    // EVENTS
    this.renderer = renderer;

    this.#container.style.touchAction = 'none';



    window.addEventListener('resize', () => {

      this.onWindowResize(self)
    });

    self.loadTTF(this.#options, (font) => {
      self.#font = font;
      self.refreshText(options)

    });
    this.openGUI()
  }

  onWindowResize(self) {

    self.size = {
      width: window.innerWidth,
      height: window.innerHeight
    };

    self.#camera.aspect = window.innerWidth / window.innerHeight;
    self.#camera.updateProjectionMatrix();

    self.renderer.setSize(window.innerWidth, window.innerHeight);

  }

  createText(options = {}) {

    const geometry = options.geometry;
    const parameters=geometry.parameters;
    const bevel = parameters.bevel;
    const textbox = options.text;

    let config = {
      curveSegments: bevel.curveSegments, //该属性指定拉伸图形时曲线分成多少段。分段数越多，曲线越平滑。默认值为4

      bevelAngle: bevel.angle,
      bevelOffset: bevel.offset,
      bevelThickness: bevel.thickness, //该属性指定斜角的深度。斜角是前后面和拉伸体之间的倒角。该值定义斜角进入图形的深度。默认值为10。
      bevelSize: bevel.size, //该属性指定斜角的高度。默认值为8
      bevelEnabled: bevel.enabled, //如果这个属性设置为true，就会有斜角。默认值为false
      bevelSegments: bevel.segments, //该属性定义斜角的分段数。分段数越多，斜角越平滑。默认值为3
      font: this.#font,
      steps: parameters.steps || 1, //该属性指定拉伸体被分成多少段。默认值为1
      size: textbox.fontSize, //该属性指定文本的大小。默认值为100
      height: textbox.height, //该属性指定拉伸的长度（深度）。默认值为50
      depth: parameters.depth,


      material: null, //该属性定义的是前后面所用材质的索引。使用THREE.SceneUtils.createMultiMaterialObject函数来创建网格
      extrudeMaterial: null,
      uvGenerato: null,
      spacing: 2, // 值可以按需调整，默认是1

    };

    if (textbox.charSpacing == 0) {

      const textGeo = new TextGeometry(textbox.content, config);
      textGeo.computeBoundingBox();
      textGeo.center();
      this.#textGeo = textGeo;
      const materials = this.createMaterials(options)
      const textMesh = new Mesh(textGeo, materials);






      this.#group.add(textMesh);
      this.textMesh = textMesh;
      if (options.autoClip)
      {
        autoClip(this.#camera, textMesh);
      }
    } else {
      const charSpacing = textbox.charSpacing;
      const characters = [];
      var totalWidth = 0;
      const text = textbox.content;
      for (let i = 0; i < text.length; i++) {
        const char = text[i];
        const geometry = new TextGeometry(char, config);

        // 计算字符的包围盒以获取实际宽度
        geometry.computeBoundingBox();
        geometry.center();
        const width = geometry.boundingBox.max.x - geometry.boundingBox.min.x;

        const materials = this.createMaterials(options)

        const textMesh = new Mesh(geometry, materials);

        // 记录字符宽度和对应的 Mesh
        characters.push({
          mesh: textMesh,
          width: width,
        });

        // 累加总宽度（包括间距）
        totalWidth += width + (i < text.length - 1 ? charSpacing : 0);

      }

      // 3. 调整位置（居中显示）
      let currentX = -totalWidth / 2; // 从左侧开始
      characters.forEach((char) => {
        char.mesh.position.x = currentX + char.width / 2;
        currentX += char.width + charSpacing;
      });
      let textMesh = this.getGrouo({
        x: 0,
        y: 0
      });
      characters.forEach((char) => textMesh.add(char.mesh));
      this.#group.add(textMesh);
      this.textMesh = textMesh;

      if (options.autoClip)
      {
        autoClip(this.#camera, textMesh);
      }
    }

    //this.#camera = this.showText(options)
  }

  refreshText(options = {}) {

    this.#group.remove(this.textMesh);



    this.createText(options);

  }

  render() {

    this.#group.rotation.y += (this.#targetRotation - this.#group.rotation.y) * 0.05;

    this.#camera.lookAt(this.cameraTarget);

    this.renderer.clear();
    this.renderer.render(this.scene, this.#camera);

  }

  initControls() {

    const controls = new OrbitControls(this.#camera, this.renderer.domElement);

    // 如果使用animate方法时，将此函数删除
    //controls.addEventListener( 'change', render );
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    controls.enableDamping = true;
    //动态阻尼系数 就是鼠标拖拽旋转灵敏度
    //controls.dampingFactor = 0.25;
    //是否可以缩放
    controls.enableZoom = true;
    //是否自动旋转
    controls.autoRotate = false;
    //设置相机距离原点的最远距离
    controls.minDistance = 20;
    //设置相机距离原点的最远距离
    controls.maxDistance = 10000;
    //是否开启右键拖拽
    controls.enablePan = true;

    this.#controls = controls;
  }

  getScene(sceneStyle = {}) {
    let scene = new Scene();
    
    
    scene.background = new Color(sceneStyle.background.color);
    scene.fog = new Fog(sceneStyle.fog.color,sceneStyle.fog.near ,sceneStyle.fog.far );
 //   scene.background = null; // new Color(0x000000);
    const plane = new Mesh(
      new PlaneGeometry(10000, 10000),
      new MeshBasicMaterial(sceneStyle.plane)
    );

    //scene.add(plane)





    return scene;
  }
  getGrouo(position = { y: 180, x: 0 }) {
    let group = new Group();
    group.position.y = position.y;

    group.position.x = position.x;

    return group;
  }


}


export default Render3DText;